package report

import (
	"fmt"
	"os"
	"strings"
	"time"

	"mongoscan/checks"
)

// 生成HTML报告
func GenerateHTMLReport(status *checks.ServerStatus, filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	// HTML头部
	fmt.Fprintf(file, `<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>MongoDB 巡检报告</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
        h1, h2, h3 { color: blue; font-weight: bold; }
        table { border-collapse: collapse; width: 80%%; max-width: 1200px; margin: 20px auto; }
        th, td { border: 1px solid #000; padding: 8px; text-align: left; height: 28px; }
        th { background-color: #f2f2f2; font-weight: bold; }
        .section { margin-bottom: 30px; }
        .title-container { text-align: center; margin-bottom: 20px; }
        .timestamp { margin-bottom: 10px; color: #666; }
    </style>
</head>
<body>
    <div class="title-container">
        <h1>MongoDB 巡检报告</h1>
        <div class="timestamp">生成时间：%s</div>
    </div>
`, time.Now().Format("2006-01-02 15:04:05"))

	// 服务器基础状态
	generateServerStatus(file, status)

	// 数据库信息
	generateDatabaseStats(file, status)

	// 慢查询
	generateSlowQueryHTML(file, status)

	// 连接与客户端
	generateConnectionsStatus(file, status)

	// 内存与资源使用
	generateMemoryStatus(file, status)

	// 锁与队列
	generateLockStatus(file, status)
	generateQueueStatus(file, status)

	// 操作计数器
	generateOpCounters(file, status)

	// 存储引擎
	generateStorageEngine(file, status)

	// 副本集状态
	generateReplicationStatus(file, status)

	// 网络与I/O
	generateNetworkStatus(file, status)

	// 断言
	generateAssertsStatus(file, status)

	// HTML尾部
	fmt.Fprintln(file, `</body>
</html>`)

	return nil
}

func generateServerStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>服务器信息</h2>
<table border="1">
  <tr>
    <th>启动时长</th>
    <th>存活状态</th>
    <th>版本</th>
	<th>端口</th>
    <th>主机</th>
    <th>进程</th>
    <th>架构</th>
  </tr>
  <tr>
    <td>%d天</td>
    <td>%t</td>
    <td>%s</td>
	 <td>%d</td>
    <td>%s</td>
    <td>%s (PID: %d)</td>
    <td>%s</td>
  </tr>
</table>
</div>
`, status.Uptime/60/60/12, status.Alive, status.Version, status.Port, status.Host, status.Process, status.PID, status.OsArch)
}

func generateDatabaseStats(file *os.File, stats *checks.ServerStatus) {

	fmt.Fprintf(file, `
<div class="section">
    <h2>数据库总览</h2>
    <table>
        <tr>
            <th>库总数</th>
            <th>文档总数</th>
            <th>数据大小(GB)</th>
            <th>存储大小(GB)</th>
            <th>索引总数</th>
            <th>索引大小(GB)</th>
        </tr>
        <tr>
            <td>%d</td>
            <td>%d</td>
            <td>%.2f</td>
            <td>%.2f</td>
            <td>%d</td>
            <td>%.2f</td>
        </tr>
    </table>
</div>`,
		len(stats.DatabaseStats),                                       // 库总数
		stats.TotalDatabaseStats.Objects,                               // 文档总数
		float64(stats.TotalDatabaseStats.DataSize)/(1024*1024*1024),    // 数据大小(GB)
		float64(stats.TotalDatabaseStats.StorageSize)/(1024*1024*1024), // 存储大小(GB)
		stats.TotalDatabaseStats.Indexes,                               // 索引数
		float64(stats.TotalDatabaseStats.IndexSize)/(1024*1024*1024),   // 索引大小(GB)
	)

	fmt.Fprintf(file, `<div class="section">
        <h2>数据库详情</h2>
        <table>
            <tr>
                <th>数据库名</th>
                <th>文档数</th>
                <th>数据大小(MB)</th>
                <th>存储大小(MB)</th>
                <th>索引数</th>
                <th>索引大小(MB)</th>
            </tr>`)

	for _, db := range stats.DatabaseStats {
		fmt.Fprintf(file, `
            <tr>
                <td>%s</td>
                <td>%d</td>
                <td>%.2f</td>
                <td>%.2f</td>
                <td>%d</td>
                <td>%.2f</td>
            </tr>`,
			db.Name, db.Objects,
			db.DataSize/1024/1024,
			db.StorageSize/1024/1024,
			db.Indexes,
			db.IndexSize/1024/1024)
	}
	fmt.Fprintf(file, `    </table>
</div>`)
}

func generateConnectionsStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>连接与客户端</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>当前连接数</td><td>%d</td></tr>
        <tr><td>可用连接数</td><td>%d</td></tr>
        <tr><td>总创建连接数</td><td>%d</td></tr>
        <tr><td>活动连接</td><td>%d</td></tr>
        <tr><td>活跃客户端总量</td><td>%d</td></tr>
        <tr><td>活跃读客户端</td><td>%d</td></tr>
        <tr><td>活跃写客户端</td><td>%d</td></tr>
    </table>
</div>
`, status.Connections.Current, status.Connections.Available, status.Connections.TotalCreated,
		status.Connections.Active, status.GlobalLock.ActiveClients.Total,
		status.GlobalLock.ActiveClients.Readers, status.GlobalLock.ActiveClients.Writers)
}

func generateMemoryStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>内存与资源使用</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>堆内存使用</td><td>%s</td></tr>
        <tr><td>常驻内存</td><td>%s</td></tr>
        <tr><td>虚拟内存</td><td>%s</td></tr>
        <tr><td>最大常驻内存</td><td>%s</td></tr>
        <tr><td>缺页错误数</td><td>%d</td></tr>
        <tr><td>页面回收</td><td>%d</td></tr>
        <tr><td>用户态 CPU 时间</td><td>%.2f秒</td></tr>
        <tr><td>内核态 CPU 时间</td><td>%.2f秒</td></tr>
    </table>
</div>
`, formatBytes(status.ExtraInfo.HeapUsageBytes), formatBytes(status.Mem.Resident),
		formatBytes(status.Mem.Virtual), formatBytes(status.ExtraInfo.MaxResidentSetKB*1024),
		status.ExtraInfo.PageFaults, status.ExtraInfo.PageReclaims,
		float64(status.ExtraInfo.UserTimeMicroseconds)/1000000,
		float64(status.ExtraInfo.SystemTimeMicroseconds)/1000000)
}

func generateLockStatus(file *os.File, status *checks.ServerStatus) {
	// 计算平均每操作等待时间（毫秒）
	totalOps := status.Opcounters.Command + status.Opcounters.Query +
		status.Opcounters.Insert + status.Opcounters.Update +
		status.Opcounters.Delete
	avgWaitTime := float64(0)
	if totalOps > 0 {
		avgWaitTime = float64(status.LockStats.GlobalLockTotalTime) / 1000 / float64(totalOps)
	}

	fmt.Fprintf(file, `
<div class="section">
    <h2>锁状态分析</h2>
    <table>
		<tr><th>项目</th><th>值</th></tr>
        <tr><td>全局锁总等待时间</td><td>%.2f 秒</td></tr>
        <tr><td>平均每操作等待时间</td><td>%.2f 毫秒</td></tr>
        <tr><td>当前等待队列总数</td><td>%d</td></tr>
        <tr><td>读操作等待数</td><td>%d</td></tr>
        <tr><td>写操作等待数</td><td>%d</td></tr>
        <tr><td>全局写锁占比</td><td>%.2f%%</td></tr>
        <tr><td>数据库写锁占比</td><td>%.2f%%</td></tr>
    </table>
</div>
`,
		float64(status.LockStats.GlobalLockTotalTime)/1000000, // 微秒转秒
		avgWaitTime,
		status.LockStats.CurrentQueueReaders+status.LockStats.CurrentQueueWriters,
		status.LockStats.CurrentQueueReaders,
		status.LockStats.CurrentQueueWriters,
		status.LockStats.GlobalWriteLockPct,
		status.LockStats.DatabaseWriteLockPct)
}

func generateQueueStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>队列信息</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>当前队列总量</td><td>%d</td></tr>
        <tr><td>读队列数</td><td>%d</td></tr>
        <tr><td>写队列数</td><td>%d</td></tr>
    </table>
</div>
`, status.GlobalLockCurrentQueue.Total, status.GlobalLockCurrentQueue.Readers,
		status.GlobalLockCurrentQueue.Writers)
}

func generateOpCounters(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>操作计数器</h2>
    <h3>基础操作</h3>
    <table>
        <tr><th>操作类型</th><th>计数</th><th>副本集计数</th></tr>
        <tr><td>Insert</td><td>%d</td><td>%d</td></tr>
        <tr><td>Query</td><td>%d</td><td>%d</td></tr>
        <tr><td>Update</td><td>%d</td><td>%d</td></tr>
        <tr><td>Delete</td><td>%d</td><td>%d</td></tr>
        <tr><td>GetMore</td><td>%d</td><td>%d</td></tr>
        <tr><td>Command</td><td>%d</td><td>%d</td></tr>
    </table>
</div>
`, status.Opcounters.Insert, status.OpcountersRepl.Insert,
		status.Opcounters.Query, status.OpcountersRepl.Query,
		status.Opcounters.Update, status.OpcountersRepl.Update,
		status.Opcounters.Delete, status.OpcountersRepl.Delete,
		status.Opcounters.GetMore, status.OpcountersRepl.GetMore,
		status.Opcounters.Command, status.OpcountersRepl.Command)
}

func generateStorageEngine(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>存储引擎 (WiredTiger)</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>缓存总大小</td><td>%s</td></tr>
        <tr><td>缓存使用量</td><td>%s</td></tr>
        <tr><td>缓存脏数据量</td><td>%s</td></tr>
        <tr><td>未修改页淘汰数</td><td>%d</td></tr>
        <tr><td>缓存读入页数</td><td>%d</td></tr>
        <tr><td>缓存写出页数</td><td>%d</td></tr>
    </table>
</div>
`, formatBytes(status.WiredTiger.Cache.MaxBytesConfigured),
		formatBytes(status.WiredTiger.Cache.BytesInCache),
		formatBytes(status.WiredTiger.Cache.DirtyBytes),
		status.WiredTiger.Cache.UnmodifiedPagesEvicted,
		status.WiredTiger.Cache.PagesReadIntoCache,
		status.WiredTiger.Cache.PagesWrittenFromCache)
}

func generateReplicationStatus(file *os.File, status *checks.ServerStatus) {
	if status.Repl.IsMaster || status.Repl.Secondary {
		fmt.Fprintf(file, `<div class="section">
    <h2>副本集状态</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>主节点</td><td>%t</td></tr>
        <tr><td>从节点</td><td>%t</td></tr>
        <tr><td>复制延迟</td><td>%d秒</td></tr>
        <tr><td>成员主机列表</td><td>%s</td></tr>
        <tr><td>Oplog 缓冲区操作数</td><td>%d</td></tr>
        <tr><td>Oplog 缓冲大小</td><td>%s</td></tr>
        <tr><td>复制批次数量</td><td>%d</td></tr>
        <tr><td>复制批处理耗时</td><td>%d毫秒</td></tr>
        <tr><td>复制网络流量</td><td>%s</td></tr>
        <tr><td>复制 GetMore 操作</td><td>%d</td></tr>
        <tr><td>复制操作总数</td><td>%d</td></tr>
    </table>
</div>
`, status.Repl.IsMaster, status.Repl.Secondary,
			status.Repl.Oplog.TimeDiff,
			strings.Join(status.Repl.Hosts, ", "),
			status.Metrics.Repl.Buffer.Count,
			formatBytes(status.Metrics.Repl.Buffer.SizeBytes),
			status.Metrics.Repl.Apply.Batches.Num,
			status.Metrics.Repl.Apply.Batches.TotalMillis,
			formatBytes(status.Metrics.Repl.Network.Bytes),
			status.Metrics.Repl.Network.Getmores,
			status.Metrics.Repl.Network.Ops)
	}
}

func generateNetworkStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>网络与 I/O</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>网络接收量</td><td>%s</td></tr>
        <tr><td>网络发送量</td><td>%s</td></tr>
    </table>
</div>
`, formatBytes(status.Network.BytesIn), formatBytes(status.Network.BytesOut))
}

func generateAssertsStatus(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `<div class="section">
    <h2>断言</h2>
    <table>
        <tr><th>项目</th><th>值</th></tr>
        <tr><td>用户断言数</td><td>%d</td></tr>
        <tr><td>警告断言数</td><td>%d</td></tr>
    </table>
</div>
`, status.Asserts.User, status.Asserts.Warning)
}

func formatBytes(bytes int) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := int64(unit), 0
	for n := int64(bytes) / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp])
}

func generateSlowQueryHTML(file *os.File, status *checks.ServerStatus) {
	fmt.Fprintf(file, `
<div class="section">
    <h2>慢查询统计</h2>
    <table>
        <tr>
            <th>时间范围</th>
            <th>慢查询数</th>
        </tr>
        <tr>
            <td>24小时</td>
            <td>%d</td>
        </tr>
        <tr>
            <td>7天</td>
            <td>%d</td>
        </tr>
        <tr>
            <td>30天</td>
            <td>%d</td>
        </tr>
        <tr>
            <td>全部</td>
            <td>%d</td>
        </tr>
    </table>
</div>`,
		status.SlowQueryStats.Last24H,
		status.SlowQueryStats.Last7D,
		status.SlowQueryStats.Last30D,
		status.SlowQueryStats.Total)
}
